package logging

import (
	"context"
	"fmt"
	"v8s/logger"
	"v8s/opensearchext"

	"go.uber.org/zap"

	"github.com/opensearch-project/opensearch-go"
	"github.com/opensearch-project/opensearch-go/opensearchapi"
)

type (
	LoggingRequest interface {
		Do(ctx context.Context, transport opensearchapi.Transport) (*opensearchapi.Response, error)
	}
	LoggingRequestResult struct {
		LR       LoggingRequest
		Err      error
		Responce *opensearchapi.Response
		client   *opensearch.Client
	}
	LoggingRepository struct {
		log *zap.SugaredLogger

		client *opensearch.Client
	}
	LoggingIndexAlias struct {
		Index string
		Alias string
	}
)

func CreateLoggingRepository(clientAPI *opensearch.Client) *LoggingRepository {
	return &LoggingRepository{
		log: logger.Logger().Named("logging-repository").Sugar(),

		client: clientAPI,
	}

}

func (r *LoggingRepository) CreateUser(username, password string) *LoggingRequestResult {
	cur := opensearchext.CreateUserRequest{
		User:         username,
		Password:     password,
		BackendRoles: opensearchext.OpensearchBackendRoles,
	}
	return &LoggingRequestResult{LR: cur,
		client: r.client,
	}
}

/*BACKLOG ALIASES
func (r *LoggingRepository) CreateAliases(aliases []LoggingIndexAlias) *LoggingRequestResult {
	actions := make([]opensearchext.Action, 0)
	for _, a := range aliases {
		actions = append(actions, opensearchext.Action{ActionName: "add", IndexName: a.Index, Alias: a.Alias})
	}
	alias := opensearchext.Alias{
		Actions: actions,
	}
	return &LoggingRequestResult{LR: alias,
		client: r.client,
	}
}
*/

func (r *LoggingRepository) MapUserRole(username, roleName string) *LoggingRequestResult {
	crm := opensearchext.MapRoleUserRequest{
		RoleName: roleName,
		Users:    []string{username},
	}
	return &LoggingRequestResult{LR: crm,
		client: r.client,
	}
}

func (r *LoggingRepository) CreateRole(roleName string, indexPatterns []string) *LoggingRequestResult {
	crr := opensearchext.CreateRoleRequest{
		RoleName:           roleName,
		ClusterPermissions: opensearchext.OpensearchClusterPermissions,
		IndexPermissions: []opensearchext.IndexPermission{
			{
				IndexPatterns:  indexPatterns,
				AllowedActions: opensearchext.OpensearchIndexAllowedActions,
			},
		},
	}
	return &LoggingRequestResult{LR: crr,
		client: r.client,
	}
}

func (r *LoggingRepository) UpdateRole(roleName string, indexPatterns []string) *LoggingRequestResult {
	urr := opensearchext.UpdateRoleRequest{
		RoleName: roleName,
		Body: []opensearchext.UpdateBody{
			{
				IndexPermissions: opensearchext.IndexPermission{
					IndexPatterns:  indexPatterns,
					AllowedActions: opensearchext.OpensearchIndexAllowedActions,
				},
			},
		},
	}
	return &LoggingRequestResult{LR: urr,
		client: r.client,
	}
}

func (r *LoggingRepository) CreateIndexPattern(p, timeField string, dashBoardClient *opensearch.Client) *LoggingRequestResult {
	cipr := opensearchext.CreateIndexPatternsRequest{
		Attribute: opensearchext.IndexPatterns{
			Title:         p,
			TimeFieldName: timeField,
		},
	}
	return &LoggingRequestResult{LR: cipr,
		client: dashBoardClient,
	}
}

func PerformRequests(ctx context.Context, requests []*LoggingRequestResult) error {
	for _, request := range requests {
		if request == nil {
			continue
		}
		responce, err := request.LR.Do(ctx, request.client)
		request.Err = err
		request.Responce = responce
		if err != nil {
			fmt.Errorf("error taking place on request '%v'", request)
		}
	}
	return nil
}
